package br.urca.controller.webservice;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;

import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;

import br.com.caelum.vraptor.Controller;
import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.view.Results;
import br.urca.dao.AlunosCursoDAO;
import br.urca.dao.AproveitamentoDAO;
import br.urca.dao.DisciplinaDAO;
import br.urca.dao.DisciplinasCursadasDAO;
import br.urca.dao.DisciplinasMatriculadasDAO;
import br.urca.dao.HistoricoDAO;
import br.urca.dao.OfertaDAO;
import br.urca.model.AlunoCurso;
import br.urca.model.Aproveitamento;
import br.urca.model.Disciplina;
import br.urca.model.DisciplinaCursada;
import br.urca.model.DisciplinaMatriculada;
import br.urca.model.Historico;
import br.urca.model.HistoricoDisciplina;
import br.urca.model.Oferta;
import br.urca.util.Criptografia;
import br.urca.util.CryptDoc;
import br.urca.util.Utils;

@Controller
public class WSHistoricoController {
	
	public static final String CURSANDO = "CURSANDO";
	
	private AlunosCursoDAO mCursoDAO;
	private DisciplinasCursadasDAO mCursadasDAO;
	private DisciplinasMatriculadasDAO mMatriculadasDAO;
	private DisciplinaDAO mDisciplinaDAO;
	private OfertaDAO mOfertaDAO;
	private HistoricoDAO mHistoricoDAO;
	private AproveitamentoDAO mAproveitamentoDAO;
	private Result result;
	private HttpServletRequest request;
	
	public WSHistoricoController() { }
	
	@Inject
	public WSHistoricoController(DisciplinasCursadasDAO mCursadasDAO,
			HistoricoDAO mHistoricoDAO, HttpServletRequest request,
			DisciplinasMatriculadasDAO mMatriculadasDAO,
			AlunosCursoDAO mCursoDAO, AproveitamentoDAO mAproveitamentoDAO,
			OfertaDAO mOfertaDAO, DisciplinaDAO mDisciplinaDAO, Result result) {
		this.mCursadasDAO = mCursadasDAO;
		this.mDisciplinaDAO = mDisciplinaDAO;
		this.mMatriculadasDAO = mMatriculadasDAO;
		this.mOfertaDAO = mOfertaDAO;
		this.mCursoDAO = mCursoDAO;
		this.mHistoricoDAO = mHistoricoDAO;
		this.mAproveitamentoDAO = mAproveitamentoDAO;
		this.result = result;
		this.request = request;
	}
	
	/**
	 * @param arg0 - Matricula do aluno
	 * @param md5  - MD5 do pacote da aplicação mobile
	 */
	@Get("/"+ Utils.PATH_DISC_CURSADAS +"/{arg0},{check}")
	public void historico(String arg0, String check) {
		if ((arg0 != null) && (check != null) && (request.getHeader("Authorization") != null)){
			
			Properties properties = new Properties();
			String mMatricula = null;
			String autenticacao = null;
			
			String autorizacao = request.getHeader("Authorization");
			
			try {
				//pega somente os números da matrícula
				properties.load(new StringReader(arg0));
				mMatricula = properties.getProperty("arg0");
				
				properties.load(new StringReader(check));
				autenticacao = properties.getProperty("check");
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (autorizacao.equals(CryptDoc.getB64Auth(mMatricula, CryptDoc.SECRET_KEY_ANDROID))) {
				String chave = CryptDoc
						.encrypt(Criptografia.criptografarMD5(mMatricula + CryptDoc.SECRET_KEY_ANDROID));
				if (autenticacao.trim().equalsIgnoreCase(chave.trim())) {
					//Pega os dados do aluno
					AlunoCurso alunoCurso = mCursoDAO.buscaPorMatricula(mMatricula);
					
					List<HistoricoDisciplina> mListDisciplinas = new ArrayList<HistoricoDisciplina>();
					mListDisciplinas.clear();
					mListDisciplinas.addAll(getCursadas(mMatricula, alunoCurso.getCurso().getCodCurso()));
					mListDisciplinas.addAll(getAproveitamentos(mMatricula));
					mListDisciplinas.addAll(getDisciplinasHistorico(mMatricula));
									
					Collections.sort(mListDisciplinas, HistoricoDisciplina.POR_OFERTA);
					
					
					if ((mListDisciplinas != null) && (!mListDisciplinas.isEmpty()) && (alunoCurso != null)) {
						this.result.use(Results.json()).from(mListDisciplinas, "resposta")
							.recursive().serialize();
					} else {
						this.result.use(Results.json()).from(new ArrayList<>(), "resposta").serialize();
					}
				}
			}	
		}
	}
	
	/**
	 * @param arg0 - Matricula do aluno
	 * @param md5  - MD5 do pacote da aplicação mobile
	 */
	@Get("/"+ Utils.PATH_DISC_MATRICULADAS +"/{arg0},{check}")
	public void matriculadas(String arg0, String check) {
		
		if ((arg0 != null) && (check != null) && (request.getHeader("Authorization") != null)) {
			
			Properties properties = new Properties();
			String mMatricula = null;
			String autenticacao = null;
			String autorizacao = request.getHeader("Authorization");
			try {
				//pega somente os números da matrícula
				properties.load(new StringReader(arg0));
				mMatricula = properties.getProperty("arg0");
				
				properties.load(new StringReader(check));
				autenticacao = properties.getProperty("check");
				
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (autorizacao.equals(CryptDoc.getB64Auth(mMatricula, CryptDoc.SECRET_KEY_ANDROID))) {
				String chave = CryptDoc
						.encrypt(Criptografia.criptografarMD5(mMatricula + CryptDoc.SECRET_KEY_ANDROID));
				if (autenticacao.trim().equalsIgnoreCase(chave.trim())) {
					
					List<HistoricoDisciplina> mListDisciplinas = new ArrayList<HistoricoDisciplina>();
					HistoricoDisciplina hd;
					try { 				
						
						List<DisciplinaMatriculada> mList = this.mMatriculadasDAO.buscarPorMatricula(mMatricula);
						if (mList != null && !mList.isEmpty()) {
							for(DisciplinaMatriculada d: mList) {
									
								Oferta mOferta = null;
								Disciplina mdDisciplina = null;
								
								mOferta = mOfertaDAO.buscarPorOfertaPedido(
										d.getId().getCodOferta(), d.getId().getCodPedido());
								if (mOferta != null)
									mdDisciplina = mDisciplinaDAO.buscarPorId(
											mOferta.getCodDisciplina());
								
								hd = new HistoricoDisciplina();
								
								hd.setCodDisciplina((mOferta != null ? mOferta.getCodDisciplina() : ""));
								hd.setCreditos((mOferta != null ? mOferta.getTotalCreditos() : ""));
								
								hd.setNomeDisciplina(
										(mdDisciplina != null ? mdDisciplina.getNomeDisciplina() : "" ));
								
								hd.setCodOferta(d.getId().getCodOferta());
								hd.setCodPedido(d.getId().getCodPedido());						
								hd.setMedia(d.getMedia());
								hd.setNotaAV1(d.getNotaAV1());
								hd.setNotaAV2(d.getNotaAV2());
								hd.setNotaAVF(d.getNotaAVF());
								hd.setSituacao(d.getSituacao().getCodSituacao());
								hd.setHorario(mOferta.getHorario());
								
								mListDisciplinas.add(hd);
								
							}	
						} else {
							List<DisciplinaCursada> mListCursadas = this.mCursadasDAO.buscarPorCodOfertaCursando(Utils.PERIODO_PADRAO, mMatricula);
							
							for(DisciplinaCursada d: mListCursadas) {
									
								Oferta mOferta = null;
								Disciplina mdDisciplina = null;
								
								mOferta = mOfertaDAO.buscarPorOfertaPedido(
										d.getId().getCodOferta(), d.getId().getCodPedido());
								if (mOferta != null) {
									
									mdDisciplina = mDisciplinaDAO.buscarPorId(mOferta.getCodDisciplina());
								
									hd = new HistoricoDisciplina();
									
									hd.setCodDisciplina((mOferta != null ? mOferta.getCodDisciplina() : ""));
									hd.setCreditos((mOferta != null ? mOferta.getTotalCreditos() : ""));
									
									hd.setNomeDisciplina(
											(mdDisciplina != null ? mdDisciplina.getNomeDisciplina() : "" ));
									
									hd.setCodOferta(d.getId().getCodOferta());
									hd.setCodPedido(d.getId().getCodPedido());	
									
									if (d.getSituacao().getCodSituacao().trim().equalsIgnoreCase("AF")) {
										hd.setMedia(null);
									} else {
										hd.setMedia(d.getMedia());
									}
									
									hd.setNotaAV1(d.getNotaAV1());
									hd.setNotaAV2(d.getNotaAV2());
									hd.setNotaAVF(d.getNotaAVF());
									hd.setSituacao(d.getSituacao().getCodSituacao());	
									hd.setHorario(mOferta.getHorario());
									
									mListDisciplinas.add(hd);	
								}
							}
						}
						
	
					} catch(Exception e) {
						this.result.use(Results.json()).from(new ArrayList<>(), "resposta").serialize();
					}
					
					if (!mListDisciplinas.isEmpty()) {
						this.result.use(Results.json()).from(mListDisciplinas, "resposta")
							.recursive().serialize();
					} else {
						this.result.use(Results.json()).from(new ArrayList<>(), "resposta").serialize();
					}
				}
			}
		}
	}
	
	public List<HistoricoDisciplina> getCursadas(String matricula, String codCurso) {
		
		HistoricoDisciplina hd = null;
		List<HistoricoDisciplina> mListDisciplinas = new ArrayList<HistoricoDisciplina>(); 
		
		List<DisciplinaCursada> mList = this.mCursadasDAO.getDiscParaHistorico(matricula);
		
		for(DisciplinaCursada d: mList) {
				
			Oferta mOferta = null;
			Disciplina mdDisciplina = null;
			
			mOferta = mOfertaDAO.buscarPorOfertaPedido(
					d.getId().getCodOferta(), d.getId().getCodPedido());
			if (mOferta != null) {
				
				mdDisciplina = mDisciplinaDAO.buscarPorId(mOferta.getCodDisciplina());
			
				hd = new HistoricoDisciplina();
				
				hd.setCodDisciplina((mOferta != null ? mOferta.getCodDisciplina() : ""));
				hd.setCreditos((mOferta != null ? mOferta.getTotalCreditos() : ""));
				
				hd.setNomeDisciplina(
						(mdDisciplina != null ? mdDisciplina.getNomeDisciplina() : "" ));
				
				hd.setCodOferta(d.getId().getCodOferta());
				hd.setCodPedido(d.getId().getCodPedido());						
				hd.setMedia(d.getMedia());
				hd.setNotaAV1(d.getNotaAV1());
				hd.setNotaAV2(d.getNotaAV2());
				hd.setNotaAVF(d.getNotaAVF());
				hd.setSituacao((d.getSituacao().getCodSituacao()
						.equalsIgnoreCase("AC") ? CURSANDO : d.getSituacao()
						.getCodSituacao()));
				
				mListDisciplinas.add(hd);	
			}
		}
		//Atividade complementar da tabela histórico
		List<Historico> mListhistAtivComp = mHistoricoDAO.getAtividadesComp(matricula);
		for (Historico histAtivComp: mListhistAtivComp) {
			if (histAtivComp != null) {
				Disciplina mdDisciplina = null;
				hd = new HistoricoDisciplina();
				mdDisciplina = mDisciplinaDAO.buscarPorId(histAtivComp.getId().getCodDisciplina());
			
				hd = new HistoricoDisciplina();
				
				hd.setCodDisciplina(histAtivComp.getId().getCodDisciplina());
				hd.setCreditos(histAtivComp.getCreditos().toString());
				
				hd.setNomeDisciplina(
						(mdDisciplina != null ? mdDisciplina.getNomeDisciplina() : "" ));
				
				hd.setCodOferta(histAtivComp.getId().getOferta());
				hd.setCodPedido("");						
				hd.setMedia(null);
				hd.setNotaAV1(histAtivComp.getNotaAV1());
				hd.setNotaAV2(histAtivComp.getNotaAV2());
				hd.setNotaAVF(histAtivComp.getNotaAVF());
				hd.setSituacao(histAtivComp.getSituacao().getCodSituacao());
				mListDisciplinas.add(hd);
				
			}
		}
		return mListDisciplinas;
	}// Fim do método
	
	private List<HistoricoDisciplina> getAproveitamentos(
			String matricula) {
		
		List<Aproveitamento> mList = mAproveitamentoDAO.getDiscParaHistorico(matricula);
		AlunoCurso mAlunoCurso = mCursoDAO.buscaPorMatricula(matricula);
		List<HistoricoDisciplina> listRetorno = new ArrayList<HistoricoDisciplina>();
		HistoricoDisciplina hd;
		if (mList != null && !mList.isEmpty()) {
			for (Aproveitamento ap: mList) {
				
				hd = new HistoricoDisciplina();
				Disciplina mDisciplina = null;
				mDisciplina = mDisciplinaDAO.buscarPorId(ap.getId().getCodDisciplina());
				
				hd.setCodDisciplina((ap.getId().getCodDisciplina() != null ? ap.getId().getCodDisciplina() : ""));
				hd.setCreditos(String.valueOf(ap.getTotalCreditos()));
				
				hd.setNomeDisciplina(
						(mDisciplina != null ? mDisciplina.getNomeDisciplina() : "" ));
				
				hd.setCodOferta(ap.getOferta());
				hd.setSituacao(ap.getTipo());
				
				listRetorno.add(hd);
			}
		}
		
		return listRetorno;
	}//Fim do Método
	
	private List<HistoricoDisciplina> getDisciplinasHistorico(
			String matricula) {
		List<HistoricoDisciplina> listRetorno = new ArrayList<HistoricoDisciplina>();
		List<Historico> mList = mHistoricoDAO.getDiscParaHistorico(matricula);
		AlunoCurso mAlunoCurso = mCursoDAO.buscaPorMatricula(matricula);
		HistoricoDisciplina hd;
		if (mList != null && !mList.isEmpty()) {
			for (Historico h: mList) {
				hd = new HistoricoDisciplina();
				Disciplina mDisciplina = null;
				mDisciplina = mDisciplinaDAO.buscarPorId(h.getId().getCodDisciplina());
				hd.setCodDisciplina((h.getId().getCodDisciplina() != null ? h.getId().getCodDisciplina() : ""));
				hd.setCreditos(h.getCreditos().toString());
				hd.setCodOferta(h.getId().getOferta());
				hd.setCodPedido(h.getPedido());
				hd.setNomeDisciplina(
						(mDisciplina != null ? mDisciplina.getNomeDisciplina() : "" ));
				hd.setNotaAV1(h.getNotaAV1());
				hd.setNotaAV2(h.getNotaAV2());
				hd.setNotaAVF(h.getNotaAVF());
				hd.setMedia(h.getNota());
				hd.setSituacao(h.getSituacao().getCodSituacao());
				
				listRetorno.add(hd);
			}
		}
		
		return listRetorno;
	}
}
